/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package com.easoft.code.pos.ui.models;

import com.easoft.code.pos.util.Valores;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.table.AbstractTableModel;
import javax.swing.table.TableModel;

/**
 *
 * @author Eliu
 */
public class PojoTableModel extends AbstractTableModel implements TableModel, Iterable {

    private List data;
    private List backupData;
    private List<String> columnNames;
    private List<String> columnRealNames;
    private Class ct;
    private Integer[] editableCols;

    public PojoTableModel(List data, List<String> columnNames, List<String> columnRealNames, Class ct) {
        this.data = data;
        this.columnNames = columnNames;
        this.columnRealNames = columnRealNames;
        this.ct = ct;
    }

    public PojoTableModel(List data, List<String> columnNames, List<String> columnRealNames, Class ct, Integer[] editableCols) {
        this.data = data;
        this.columnNames = columnNames;
        this.columnRealNames = columnRealNames;
        this.ct = ct;
        this.editableCols = editableCols;
    }

    public void filterStrigData(String fieldName, String val) {
        System.out.println(val);
        if (backupData == null) { //1era vez
            backupData = new LinkedList(data);
        } else {
            data = new LinkedList(backupData);
        }
        if (val != null && !val.isEmpty()) {
            List newData = new LinkedList();
            for (Iterator i = data.iterator(); i.hasNext();) {
                try {
                    Object o = ct.cast(i.next());
                    Character chr = fieldName.charAt(0);
                    Method m = ct.getMethod("get" + chr.toString().toUpperCase() + fieldName.substring(1));
                    Object r = m.invoke(o);
                    if (r != null && r.toString().trim().toUpperCase().contains(val.trim().toUpperCase())) {
                        newData.add(o);
                    }
                } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException ex) {
                    Logger.getLogger(PojoTableModel.class.getName()).log(Level.SEVERE, null, ex);
                } catch (NoSuchMethodException | SecurityException ex) {
                    Logger.getLogger(PojoTableModel.class.getName()).log(Level.SEVERE, null, ex);
                }
            }
            System.out.println(newData.size());
            data = newData;
        }
    }

    public List getData() {
        return data;
    }

    public void setData(List data) {
        this.data = data;
    }

    @Override
    public int getRowCount() {
        return data.size();
    }

    @Override
    public String getColumnName(int column) {
        return columnNames.get(column);
    }

    @Override
    public int getColumnCount() {
        return columnNames.size();
    }

    @Override
    public void setValueAt(Object aValue, int rowIndex, int columnIndex) {
        try {
            Object row = this.data.get(rowIndex);
            for (Method m : ct.getMethods()) {
                if (m.getName().equals("set" + columnRealNames.get(columnIndex))) {
                    Class<?>[] pTypes = m.getParameterTypes();
                    Class type = pTypes[0];
                    try {
                        m.invoke(row, type.cast(aValue));
                    } catch (ClassCastException | IllegalAccessException | IllegalArgumentException ex) {
                        try {
                            Method valueOf = type.getMethod("valueOf", String.class);
                            Object castVal = valueOf.invoke(null, aValue.toString());
                            m.invoke(row, castVal);
                        } catch (NoSuchMethodException | SecurityException | IllegalAccessException | IllegalArgumentException ex1) {
                            Logger.getLogger(PojoTableModel.class.getName()).log(Level.SEVERE, null, ex1);
                        }
                    }
                }
            }
        } catch (InvocationTargetException ex) {
            Logger.getLogger(PojoTableModel.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

    @Override
    public Object getValueAt(int rowIndex, int columnIndex) {
        try {
            Object row = this.data.get(rowIndex);
            for (Method m : ct.getMethods()) {
                if (m.getName().equals("get" + columnRealNames.get(columnIndex))) {
                    Object r = m.invoke(row, new Object[]{});
                    if (r instanceof Date) {
                        SimpleDateFormat sd = new SimpleDateFormat(Valores.getConfigValue(Valores.DATE_FORMAT));
                        return sd.format(r);
                    }
                    return r;
                }
            }
        } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException ex) {
            Logger.getLogger(PojoTableModel.class.getName()).log(Level.SEVERE, null, ex);
        }
        return null;
    }

    @Override
    public Iterator iterator() {
        return data.iterator();
    }

    @Override
    public boolean isCellEditable(int rowIndex, int columnIndex) {
        if (editableCols != null) {
            for (Integer col : editableCols) {
                if (columnIndex == col) {
                    return true;
                }
            }
        }
        return false;
    }

}
